package com.kunlun.common.config;

import com.kunlun.common.utils.ResponseUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.MessageFormat;

/**
 * RestControllerAdviceI自动配置类
 */
@RestControllerAdvice
public class ControllerAdviceAutoConfig implements ResponseBodyAdvice {

    private Logger log = LogManager.getLogger();

    private static final String EXCEPTION_PATTERN = "请求异常！";

    private static final String REQUEST_PATTERN = "\n---BEGIN---\nReqURI: {0}\nParams: {1}\nMethod: {2}\nReturn: {3}\n---END---";

    @ExceptionHandler(value = {Exception.class})
    public Object handleAllException(Exception e, HttpServletRequest request, HttpServletResponse response) {
        log.info("接口调用异常", e);
        if (e instanceof NoHandlerFoundException) {
            String reqURI = request.getRequestURI().toString();
            return MessageFormat.format(EXCEPTION_PATTERN, "资源 " + reqURI + " 不存在！");
        }
        return MessageFormat.format(EXCEPTION_PATTERN, e.getMessage());
    }

    @Override
    public Object beforeBodyWrite(Object rtnMsg, MethodParameter param, MediaType mediaType, Class aClass, ServerHttpRequest req, ServerHttpResponse serverHttpResponse) {
        String clazName = param.getDeclaringClass().getName();
        String mtdName = param.getMethod().getName();
        String reqURI = req.getURI().toString();
        String reqParams = getReqParams(reqURI);

        String logMsg = getLog(reqURI, reqParams, clazName + "." + mtdName, rtnMsg.toString());
        log.info("beforeBodyWrite => " + logMsg);
        return rtnMsg;
    }

    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return true;
    }

    private String getLog(String reqURI, String reqParams, String proMethod, String rtnMsg) {
        return MessageFormat.format(REQUEST_PATTERN, reqURI, reqParams, proMethod, rtnMsg);
    }

    private String getReqParams(String reqUri) {
        StringBuilder params = new StringBuilder();
        if (reqUri.contains("?")) {
            String[] urlArray = reqUri.split("\\?");
            String[] splits = StringUtils.isNotEmpty(urlArray[1]) ? urlArray[1].split("&") : new String[0];
            for (String param : splits) {
                params.append(param);
            }
        }
        return params.toString();
    }
}
